﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.CSharp;
using System.CodeDom.Compiler;
using System.Reflection;
using System.CodeDom;
using System.IO;
using System.Diagnostics;

namespace RazorTemplateEngine
{
    public class DynamicCSharpCodeBuilder
    {
        private CSharpCodeProvider provider = null;
        private CompilerParameters option = null;
        private Assembly[] referenceAssemblies { get; set; }
        public DynamicCSharpCodeBuilder()
        {
            Init();
        }

        public DynamicCSharpCodeBuilder(AssemblyContext context)
        {
            this.referenceAssemblies = context.ReferenceAssemblies;
            Init();
        }

        private void Init()
        {
            provider = new CSharpCodeProvider();
            option = new CompilerParameters();
            option.IncludeDebugInformation = false;
            option.GenerateExecutable = false;
            option.GenerateInMemory = true;

            if (referenceAssemblies != null)
            {
                foreach (var a in referenceAssemblies)
                {
#if DEBUG
                    Debug.WriteLine(a.Location);
#endif
                    option.ReferencedAssemblies.Add(a.Location);
                }
            }
        }


        public CompilerResults Complie(CodeCompileUnit target)
        {
            if (target == null) throw new ArgumentNullException("target");
#if DEBUG
            StringWriter sw = new StringWriter();
            CodeGeneratorOptions generate_options = new CodeGeneratorOptions();
            generate_options.BlankLinesBetweenMembers = false;
            generate_options.IndentString = "\t";
            string dynamicCode = string.Empty;
            try
            {
                provider.GenerateCodeFromCompileUnit(target, sw, generate_options);
                sw.Flush();
                dynamicCode = sw.GetStringBuilder().ToString();
            }
            catch { }
            finally
            {
                sw.Close();
            }
#endif
            CompilerResults result = provider.CompileAssemblyFromDom(option, target);//, basePageCode);
            Debug.WriteLine(option.OutputAssembly);
#if DEBUG
            Debug.WriteLine(dynamicCode);
#endif
            if (result.Errors.Count != 0)
                throw new CompileErrorException(result.Errors);
            return result;
        }
    }
}
